﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MobileSales.Server.Database;
using MobileSales.Common.Logger;
using System.Security.Cryptography;
using System.Net.Mail;

namespace MobileSales.Server.Services
{
    public class AuthService : ServiceBase,IAuthService
    {
        #region Login
        public string Login(string userName, string passwdSHA1)
        {
            Employee dbEmployee = entities.Employees.Where(x => x.Login.Equals(userName)).FirstOrDefault();
            if (dbEmployee != null)
            {
                CLogger.LogDebug(dbEmployee.Passwd.ToLower() + "\n" + passwdSHA1.ToLower());
                if (dbEmployee.Passwd.ToLower().Equals(passwdSHA1.ToLower()))
                {
                    Guid token = Guid.NewGuid();
                    dbEmployee.ValidationToken = token;
                    entities.SaveChanges();
                    return token.ToString();
                }
                else
                    this.Raise("User does not exist!");
            }
            else
                this.Raise("User does not exist!");
            return null;
        } 
        #endregion

        #region RenewToken
        public string RenewToken(string token)
        {
            Employee dbEmployee = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).FirstOrDefault();
            if (dbEmployee != null)
            {
                Guid newToken = Guid.NewGuid();
                dbEmployee.ValidationToken = newToken;
                entities.SaveChanges();
                return newToken.ToString();
            }
            else
                this.Raise("Token does not exist!");
            return null;
        } 
        #endregion

        #region ChangePassword
        public void ChangePassword(string token, string oldPasswdSHA1, string newPasswdSHA1)
        {
            Employee dbEmployee = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).FirstOrDefault();
            if (dbEmployee != null)
            {
                if (dbEmployee.Passwd.Equals(oldPasswdSHA1))
                {
                    dbEmployee.Passwd = newPasswdSHA1;
                    entities.SaveChanges();
                }
                else
                {
                    this.Raise("Invalid old password");
                }
            }
            else
                this.Raise("User not found");
        }
        #endregion

        #region GetUserIdFromToken
        public int GetUserIdFromToken(string token)
        {
            int employeeId = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).Select(x => x.EmployeeId).FirstOrDefault();
            if (employeeId == 0)
                this.Raise("Could not find employee for token");
            return employeeId;
        }  
        #endregion

        #region TokenHasWebsiteAccess
        public bool TokenHasWebsiteAccess(string token)
        {
            bool hasAccess = entities.Employees.Where(x => x.ValidationToken.Equals(new Guid(token))).Select(x => x.Role.HasWebsiteAccess).FirstOrDefault();
            return hasAccess;
        } 
        #endregion

        #region RemindPassword
        public void RemindPassword(string email)
        {
            Employee dbEmployee = entities.Employees.Where(x => x.Email.Equals(email)).FirstOrDefault();
            if (dbEmployee != null)
            {
                String newPassword = this.GeneratePassword(12);
                this.SendRemindPasswordEmail(email, newPassword);
                dbEmployee.Passwd = this.CalculateSHA1(newPassword, Encoding.UTF8);
                entities.SaveChanges();
            }
            else
            {
                this.Raise("There is no corresponding employee to given email");
            }
        }

        #endregion

        #region SendRemindPasswordEmail
        private void SendRemindPasswordEmail(string email, string password)
        {
            MailAddress fromAddress = new MailAddress("no-reply@mobilesales.com");
            MailAddress toAddress = new MailAddress(email);
            var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = "[MobileSalesServer] Password reminder",
                Body = String.Format("New password: {0}", password)
            };
            var client = new SmtpClient("localhost");
            client.Send(message);
        } 
        #endregion

        #region CalculateSHA1
        private string CalculateSHA1(string text, Encoding enc)
        {
            byte[] buffer = enc.GetBytes(text);
            SHA1CryptoServiceProvider cryptoTransformSHA1 =
            new SHA1CryptoServiceProvider();
            string hash = BitConverter.ToString(
                cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "");

            return hash;
        } 
        #endregion

        #region GeneratePassword
        private string GeneratePassword(int length)
        {
            string _allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
            Random randNum = new Random();
            char[] chars = new char[length];
            int allowedCharCount = _allowedChars.Length;

            for (int i = 0; i < length; i++)
            {
                chars[i] = _allowedChars[(int)((_allowedChars.Length) * randNum.NextDouble())];
            }

            return new string(chars);
        } 
        #endregion

    }
}

